package net.zigin.nhi.could.waste.service.impl;

import net.zigin.commons.util.AssertUtil;
import net.zigin.commons.util.ParamsMapUtil;
import net.zigin.commons.util.ReflectUtil;
import net.zigin.commons.util.StringUtil;
import net.zigin.nhi.could.waste.aop.LoginAspect;
import net.zigin.nhi.could.waste.util.StringUtil2;
import net.zigin.nhi.could.waste.vo.TokenInfoBo;
import net.zigin.nhi.could.waste.constants.CommonConstants;
import net.zigin.nhi.could.waste.dao.*;
import net.zigin.nhi.could.waste.dto.SysUserDto;
import net.zigin.nhi.could.waste.exception.EpiCloudException;
import net.zigin.nhi.could.waste.model.HospitalBase;
import net.zigin.nhi.could.waste.service.SysMenuService;
import net.zigin.nhi.could.waste.service.SysRoleService;
import net.zigin.nhi.could.waste.util.HttpClientUtil;
import net.zigin.nhi.could.waste.util.JWTUtil;
import net.zigin.nhi.could.waste.util.SecurityUtil;
import net.zigin.nhi.could.waste.vo.JsonForResult;
import net.zigin.nhi.could.waste.vo.SysMenuVo;
import net.zigin.nhi.could.waste.vo.SysRoleVo;
import net.zigin.nhi.could.waste.vo.SysUserVo;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import net.zigin.nhi.could.waste.model.SysUser;
import net.zigin.nhi.could.waste.service.SysUserService;

import java.text.SimpleDateFormat;
import java.util.*;

/*#################################################################*
# 说明:以下代码通过哲勤代码生成工具自动生成    
# 工具:GeneratorCode
# 作者:mgw1986                                                  
# 生成时间:2021-9-7 19:08:56                                               
##################################################################*/


/**
 * SysUser服务实现类
 *
 * @author mgw1986
 * @version V1.0
 * @ClassName: SysUserServiceImpl
 * @date 2021-9-7 19:08:56
 */
@Service
public class SysUserServiceImpl extends AbstractServiceImpl<SysUser, String> implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private HospitalBaseMapper hospitalBaseMapper;
    @Autowired
    private SysUserHospitalMapper sysUserHospitalMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Value("${zigin.smsUrl}")
    private String smsUrl;
    @Value("${zigin.customSmsUrl}")
    private String customSmsUrl;

    @Override
    public BaseMapper<SysUser, String> getMapper() {
        return sysUserMapper;
    }

    @Override
    public String saveOrUpdate(SysUserDto userDto) {
        SysUserVo currentUser = getCurrentUser();
        // 对账号进行校验
        AssertUtil.isNull(userDto, "人员信息不能为空");
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        if (StringUtil.isNullOrEmpty(userDto.getId())) {
            AssertUtil.isNull(userDto.getName(), "账号不能为空");
            AssertUtil.isNull(userDto.getPassword(), "密码不能为空");
            //AssertUtil.isNull(userDto.getType(), "用户类型不能为空");
            SysUser sysUser = sysUserMapper.getUserByLoginName(userDto.getName());
            if (sysUser != null) {
                throw new RuntimeException("该账号已存在！");
            }
            userDto.setId(StringUtil.get32UUID());
            userDto.setCreateTime(new Date());
            userDto.setModifyTime(new Date());
            userDto.setType(currentUser.getType());
            userDto.setCreateUser(tokenInfo.getLoginName());
            userDto.setPassword(SecurityUtil.encodePassword(userDto.getPassword()));
            SysUser user = ReflectUtil.copyProperties(userDto, SysUser.class);
            sysUserMapper.insert(user);
            return user.getId();
        }
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userDto.getId());
        if (!sysUser.getName().equals(userDto.getName())) {
            SysUser sysUserTmp = sysUserMapper.getUserByLoginName(userDto.getName());
            if (sysUserTmp != null) {
                throw new RuntimeException("请重新填写登录名，该名字下账号已存在！");
            }
        }
        // 编辑
        userDto.setModifyTime(new Date());
        userDto.setModifyUser(tokenInfo.getLoginName());
        SysUser user = ReflectUtil.copyProperties(userDto, SysUser.class);
        sysUserMapper.updateByPrimaryKeySelective(user);
        return user.getId();
    }

    @Override
    public List<SysUserVo> getUserList(SysUserDto userDto) {
        Map<String, Object> paramMap = getUserParams(userDto);
        List<SysUser> users = sysUserMapper.selectListByPage(paramMap);

        // 返回角色信息
        List<SysUserVo> sysUserVos = ReflectUtil.copyProperties(users, SysUserVo.class);
        sysUserVos.forEach(userVo -> {
            List<SysRoleVo> sysRoles = sysRoleService.infoByUserId(userVo.getId());
            userVo.setRoleVoList(sysRoles);
        });
        return sysUserVos;
    }

    @Override
    public Integer getUserCount(SysUserDto userDto) {
        Map<String, Object> paramMap = getUserParams(userDto);
        return sysUserMapper.selectCount(paramMap);
    }

    private Map<String, Object> getUserParams(SysUserDto userDto) {
        return ParamsMapUtil.getInstance()
                .addParam("name", userDto.getName())
                .addParam("mobile", userDto.getMobile())
                .addParam("email", userDto.getEmail())
                .addParam("type", userDto.getType())
                .addParam("pageIndex", userDto.getPageIndex())
                .addParam("pageSize", userDto.getPageSize());
    }

    @Override
    public List<SysUserVo> infoByRoleId(String roleId) {
        List<SysUser> users = sysUserMapper.infoByRoleId(roleId);
        if (users.isEmpty()) {
            return new ArrayList<>();
        }
        return ReflectUtil.copyProperties(users, SysUserVo.class);
    }

    @Override
    public SysUserVo getUserByUserAccount(String userAccount) {
        SysUser user = sysUserMapper.getUserByLoginName(userAccount);
        return ReflectUtil.copyProperties(user, SysUserVo.class);
    }

    @Override
    public SysUserVo getCurrentUser() {
        String userAccount = JWTUtil.getUserAccount(SecurityUtils.getSubject().getPrincipal().toString());
        return sysUserMapper.getUserInfoByLoginName(userAccount);
    }

    @Override
    public SysUserVo getInfoById(String id) {
        SysUser user = sysUserMapper.selectByPrimaryKey(id);
        SysUserVo userVo = ReflectUtil.copyProperties(user, SysUserVo.class);
        userVo.setGuideCodes(Arrays.asList(user.getGuideCode().split("")));
        List<SysRoleVo> roleVos = sysRoleService.infoByUserId(id);
        AssertUtil.isNull(roleVos, "该账号未分配角色！");
        userVo.setRoleVoList(roleVos);
        List<SysMenuVo> menuVos = sysMenuService.infoByUserId(id);
        AssertUtil.isNull(menuVos, "该角色未分配菜单！");
        if (user.getType().equals("hospital") || user.getType().equals("staff")) {
            boolean allowLogin = false;
            for (SysMenuVo sysMenuVo : menuVos) {
                // 判断是否有医院端菜单
                if (sysMenuVo.getSysFlag().equals("hospital")) {
                    allowLogin = true;
                    break;
                }
            }
            if (user.getType().equals("hospital")) {
                allowLogin = true;
            }
            if (!allowLogin) {
                throw new EpiCloudException("该账号没有医院端菜单！");
            }
        }
        // 默认菜单
        if (user.getType().equals("hospital")) {
            menuVos = sysMenuService.getHospitalMenuList();
        }
        // 判断机构审核状态
        if (!userVo.getType().equals(CommonConstants.SYS_USER_TYPE_ADMIN)) {
            String hospitalBaseId = sysUserHospitalMapper.getHospitalBaseIdBySysUserId(userVo.getId());
            HospitalBase hospitalBase = hospitalBaseMapper.selectByPrimaryKey(hospitalBaseId);
            userVo.setHospitalBaseId(hospitalBaseId);
            userVo.setHospitalBaseName(hospitalBase.getName());
            if (hospitalBase.getCreditStatus().equals("wait")) {
                throw new EpiCloudException("您的账号正在审核中，请稍后再试");
            } else if (hospitalBase.getCreditStatus().equals("fail")) {
                throw new EpiCloudException("您的账号未通过审核！");
            }
        }
        userVo.setMenuVoList(menuVos);
        return userVo;
    }

    @Override
    public void modifyPassword(SysUserDto userDto) {
        AssertUtil.isNull(userDto, "用户信息不能为空");
        AssertUtil.isNull(userDto.getName(), "用户账户不能为空");
        AssertUtil.isNull(userDto.getPassword(), "用户新密码不能为空");
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        // 允许修改其他人密码
       /* UserVo currentUser = getCurrentUser();
        if(!userDto.getUserAccount().equals(currentUser.getUserAccount())){
            throw new EpiCloudException("只能修改自己的账户密码！");
        }*/
        // 通过账户获取用户信息
        SysUserVo userVo = getUserByUserAccount(userDto.getName());
        if (userVo == null) {
            throw new EpiCloudException("账户不存在！");
        }
        // 修改密码
        userVo.setPassword(SecurityUtil.encodePassword(userDto.getPassword()));
        userVo.setModifyUser(tokenInfo.getLoginName());
        SysUser user = ReflectUtil.copyProperties(userVo, SysUser.class);
        sysUserMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public void modifyPasswordWithSmsCode(SysUserDto userDto) {
        // 通过账户获取用户信息
        SysUserVo userVo = getUserByUserAccount(userDto.getMobile());
        // 修改密码
        userVo.setPassword(SecurityUtil.encodePassword(userDto.getPassword()));
        SysUser user = ReflectUtil.copyProperties(userVo, SysUser.class);
        sysUserMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public SysUserVo getUserByUserPhone(String mobile) {
        SysUser user = sysUserMapper.getUserByUserPhone(mobile);
        AssertUtil.isNull(user, "用户不存在！");
        SysUserVo userVo = ReflectUtil.copyProperties(user, SysUserVo.class);
        List<SysRoleVo> roleVos = sysRoleService.infoByUserId(user.getId());
        userVo.setRoleVoList(roleVos);
        List<SysMenuVo> menuVos = sysMenuService.infoByUserId(user.getId());
        userVo.setMenuVoList(menuVos);
        return userVo;
    }

    @Override
    public String sendMessage(String mobile) {
        int random = (int) (Math.random() * 9000 + 1000);
        String content = "【医废追溯系统】您的验证码是：" + random + "，10分钟内有效。";
        HttpClientUtil.smsCustomCode(customSmsUrl, mobile, content);
        return String.valueOf(random);
    }

    @Override
    public void checkMobileExist(String mobile) {
        AssertUtil.isNull(mobile, "手机号不能为空！");
        if (!StringUtil2.isPhone(mobile)) {
            throw new EpiCloudException("手机号格式不正确！");
        }
        Integer count = sysUserMapper.checkMobileExist(mobile);
        if (count > 0) {
            throw new EpiCloudException("该手机号下已存在账户！");
        }
    }

    @Override
    public String checkMobileExistReturnUserStaffId(String mobile) {
        AssertUtil.isNull(mobile, "手机号不能为空！");
        if (!StringUtil2.isPhone(mobile)) {
            throw new EpiCloudException("手机号格式不正确！");
        }
        Integer count = sysUserMapper.checkMobileExist(mobile);
        if (count > 0) {
            return sysUserHospitalMapper.getIdByUserPhone(mobile);
        }
        return "";
    }

    public void test() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyMMdd");
        System.out.println(format.format(date));
        System.out.println(String.format("%04d", 12));
    }

    @Override
    public void updateGuideCode(List<String> guideCode) {
        String code = guideCode.stream().reduce((s1, s2) -> s1 + s2).get();
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        SysUser sysUser = new SysUser();
        sysUser.setId(tokenInfo.getUserId());
        sysUser.setGuideCode(code);
        sysUserMapper.updateByPrimaryKeySelective(sysUser);
    }
}